import resultful from './resultful.js' //返回数据构造
import apitime from './apitime.js' //API限流
import vconf from '../utils/vconf.js'
const config = vconf('config.yml')
const { apitimecount } = config

//检测CMAKE令牌
const check_cmake = async (fastify, request, reply, code = 'SUCCESS', next) => {
  if (code === 'JUMP_CHECK') {
    next()
    return
  }

  const { id, raw } = request
  if (code === 'SUCCESS') {
    if (raw.method === 'GET') {
      //读取是否 接口有redis缓存
      const cache = await fastify.get_redis(`api_${fastify.md5(raw.url)}`)
      cache ? reply.send(cache) : next()
    } else {
      //POST请求跳过检测缓存直接执行
      next()
    }
  } else {
    reply.code(403).send(resultful(code))
  }
}

//检测JWT令牌
const check_jwt = (fastify, request, reply, next) => {
  const { raw } = request
  if (raw.method === 'OPTIONS') {
    reply.code(200).send()
    return
  }
  request.jwtVerify((err, decoded) => {
    let url_idx = raw.url.indexOf('?')
    let url_str = url_idx !== -1 ? raw.url.substring(0, url_idx) : raw.url
    //没有携带令牌时 判断是否时授权路由=> 检测true为是授予令牌的接口 ,否则返回状态码 WHEREIS_CRACK
    let state = global.jump_auth.get(url_str) ? 'JUMP_CHECK' : 'WHEREIS_CRACK'
    if (err && err.name === 'TokenExpiredError') {
      reply.code(401).send(resultful('UNMAKETOKEN_RUBBISH'))
      return
    }
    if (err && err.name === 'JsonWebTokenError') {
      reply.code(403).send(resultful('UNMAKETOKEN_RUBBISH'))
      return
    }
    if (err === null) state = 'SUCCESS'
    check_cmake(fastify, request, reply, state, next)
  })
}

const ORIGIN = ['Access-Control-Allow-Origin', '*']
const HEADERS = ['Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With']
const METHODS = ['Access-Control-Allow-Methods', 'POST,GET,OPTIONS']

export default function(fastify) {
  //请求
  fastify.addHook('onRequest', (request, reply, next) => {
    const { raw, query, body, id, headers } = request
    const url = raw.url
    if(url === '/favicon.ico') {
      reply.code(404).send()
    } else {

      reply.header(...ORIGIN)
      reply.header(...HEADERS)
      reply.header(...METHODS)
      // next()
      
      let { time, count } = Object.assign({}, apitimecount, query.apitime)
      if(global.api_limit[`limit_${url}`]) {
        [time, count] = global.api_limit[`limit_${url}`]
      }
      apitime(fastify, url, time, count).then((bool) => {
        if (!bool) {
          reply.code(401).send(resultful('API_OutTime'))
        } else {
          check_jwt(fastify, request, reply, next)
        }
      })
    }
  })
}
